package com.nbcio.iot.controller;

import com.nbcio.common.core.domain.R;
import com.nbcio.iot.ingest.IotIngestionService;
import com.nbcio.iot.protocol.tcp.TcpServerManager;
import com.nbcio.iot.protocol.udp.UdpServerManager;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * TCP/UDP服务器控制器
 * 提供TCP/UDP服务器的管理和监控功能
 */
@Slf4j
@RestController
@RequestMapping("/iot/tcp-udp")
@RequiredArgsConstructor
public class TcpUdpController {

    private final TcpServerManager tcpServerManager;
    private final UdpServerManager udpServerManager;
    private final IotIngestionService ingestionService;
    private final ObjectMapper objectMapper = new ObjectMapper();

    @PostConstruct
    public void init() {
        // 设置TCP服务器消息监听器
        if (tcpServerManager != null) {
            tcpServerManager.setMessageListener((topic, payload) -> {
                String routedTopic = buildDeviceTopic(topic, payload);
                log.info("[TCP-UDP-CTL] TCP消息转发到数据处理, topic={}", routedTopic);
                ingestionService.handleIncoming(routedTopic, payload);
            });
        }
        
        // 设置UDP服务器消息监听器
        if (udpServerManager != null) {
            udpServerManager.setMessageListener((topic, payload) -> {
                String routedTopic = buildDeviceTopic(topic, payload);
                log.info("[TCP-UDP-CTL] UDP消息转发到数据处理, topic={}", routedTopic);
                ingestionService.handleIncoming(routedTopic, payload);
            });
        }

    }

    /**
     * 将 TCP/UDP 的原始 topic 重写为 devices/{deviceCode}/up，以复用现有入站逻辑
     */
    private String buildDeviceTopic(String rawTopic, String payload) {
        // 1) JSON 解析优先
        try {
            if (payload != null && !payload.isEmpty()) {
                JsonNode node = objectMapper.readTree(payload);
                JsonNode deviceCodeNode = node.get("deviceCode");
                if (deviceCodeNode != null && !deviceCodeNode.isNull()) {
                    String deviceCode = deviceCodeNode.asText();
                    if (deviceCode != null && !deviceCode.isEmpty()) {
                        String routed = "devices/" + deviceCode + "/up";
                        log.info("[TCP-UDP-CTL] route via JSON deviceCode={}, topic={}", deviceCode, routed);
                        return routed;
                    }
                }
            }
        } catch (Exception e) {
            log.warn("[TCP-UDP-CTL] JSON parse failed for routing: {}", e.getMessage());
        }

        // 2) 正则回退提取 deviceCode
        try {
            if (payload != null) {
                java.util.regex.Matcher m = java.util.regex.Pattern
                    .compile("\\\"deviceCode\\\"\\s*:\\s*\\\"([^\\\"]+)\\\"")
                    .matcher(payload);
                if (m.find()) {
                    String deviceCode = m.group(1);
                    if (deviceCode != null && !deviceCode.isEmpty()) {
                        String routed = "devices/" + deviceCode + "/up";
                        log.info("[TCP-UDP-CTL] route via REGEX deviceCode={}, topic={}", deviceCode, routed);
                        return routed;
                    }
                }
            }
        } catch (Exception ignore) { }

        // 3) 兜底：保持原始 topic，便于排查
        String fallback = rawTopic == null ? "tcp/unknown" : rawTopic;
        log.info("[TCP-UDP-CTL] route fallback, keep rawTopic={}", fallback);
        return fallback;
    }

    /**
     * 获取TCP服务器状态
     */
    @GetMapping("/tcp/status")
    public R<Map<String, Object>> getTcpStatus() {
        Map<String, Object> status = new HashMap<>();
        status.put("running", tcpServerManager.getClientCount() > 0);
        status.put("clientCount", tcpServerManager.getClientCount());
        status.put("clientIds", tcpServerManager.getClientIds());
        return R.ok(status);
    }

    /**
     * 获取UDP服务器状态
     */
    @GetMapping("/udp/status")
    public R<Map<String, Object>> getUdpStatus() {
        Map<String, Object> status = new HashMap<>();
        status.put("running", udpServerManager.isRunning());
        status.put("port", udpServerManager.getServerPort());
        return R.ok(status);
    }

    /**
     * 向TCP客户端发送消息
     */
    @PostMapping("/tcp/send")
    public R<Void> sendTcpMessage(@RequestBody Map<String, String> body) {
        String clientId = body.get("clientId");
        String message = body.get("message");
        
        if (clientId == null || message == null) {
            return R.fail("客户端ID和消息内容不能为空");
        }
        
        boolean success = tcpServerManager.sendToClient(clientId, message);
        if (success) {
            return R.ok();
        } else {
            return R.fail("发送失败，客户端可能已断开连接");
        }
    }

    /**
     * 向UDP客户端发送消息
     */
    @PostMapping("/udp/send")
    public R<Void> sendUdpMessage(@RequestBody Map<String, Object> body) {
        String clientAddress = (String) body.get("clientAddress");
        Integer clientPort = (Integer) body.get("clientPort");
        String message = (String) body.get("message");
        
        if (clientAddress == null || clientPort == null || message == null) {
            return R.fail("客户端地址、端口和消息内容不能为空");
        }
        
        boolean success = udpServerManager.sendToClient(clientAddress, clientPort, message);
        if (success) {
            return R.ok();
        } else {
            return R.fail("发送失败");
        }
    }

    /**
     * 广播TCP消息给所有客户端
     */
    @PostMapping("/tcp/broadcast")
    public R<Void> broadcastTcpMessage(@RequestBody Map<String, String> body) {
        String message = body.get("message");
        if (message == null) {
            return R.fail("消息内容不能为空");
        }
        
        tcpServerManager.broadcast(message);
        return R.ok();
    }

    /**
     * 获取TCP连接的客户端列表
     */
    @GetMapping("/tcp/clients")
    public R<Set<String>> getTcpClients() {
        return R.ok(tcpServerManager.getClientIds());
    }
}

